#pragma once
#include "common.hpp"

#include "logger.hpp"
#include <jsoncpp/json/json.h>
#include "socket.hpp"
using namespace logger_module;
using namespace socket_module;

class Request
{
public:
    Request(){}
    Request(int x,int y,char oper)
    :_x(x),
    _y(y),
    _oper(oper){}
    std::string Serialize()
    {
        Json::Value root;
        root["x"]=_x;
        root["y"]=_y;
        root["oper"]=std::string(1,_oper);
        Json::FastWriter writer;
        std::string s=writer.write(root);
        return s;
    }
    bool Deserialiaze(std::string&in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok=reader.parse(in,root);
        if(ok)
        {
            _x=root["x"].asInt();
            _y=root["y"].asInt();
            _oper=root["oper"].asString()[0];
        }
        return ok;
    }
    ~Request(){}
    int X() { return _x; }
    int Y() { return _y; }
    char Oper() { return _oper; }
private:
    int _x;
    int _y;
    char _oper;
};
class Response
{
public:
    Response(){}
    Response(int result,int code)
    :_result(result),
    _code(code){}
    std::string Serialize()
    {
        Json::Value root;
        root["result"]=_result;
        root["code"]=_code;
        Json::FastWriter writer;
        return writer.write(root);
    }
    bool Deserialize(std::string&in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok=reader.parse(in,root);
        if(ok)
        {
            _result=root["result"].asInt();
            _code=root["code"].asInt();
        }
        return ok;
    }
    void SetResult(int res)
    {
        _result =res;
    }
    void SetCode(int code)
    {
        _code=code;
    }\
private:
    int _result;
    int _code; 
};
const std::string sep="\r\n";
using func_t = std::function<Response(Request&req)>;
class Protocol
{
public:
    Protocol(func_t func):_func(func){}
    std::string Encode(const std::string &jsonstr)
    {
        std::string len =std::to_string(jsonstr.size());
        return len+sep+jsonstr+sep;
    }
    bool Decode(std::string&buffer,std::string*package)
    {
        ssize_t pos=buffer.find(sep);
        if(pos==std::string::npos)
            return false;
        std::string package_len_str=buffer.substr(0,pos);
        int package_len_int =std::stoi(package_len_str);
        int target_len=package_len_str.size()+package_len_int+2*sep.size();
        if(buffer.size()<target_len)
            return false;
        *package=buffer.substr(pos+sep.size(),package_len_int);
        buffer.erase(0,target_len);//清理缓冲区
        return true;
    }
    void GetRequest(std::shared_ptr<Socket>&sock,InetAddr&client)
    {
        std::string buffer_queue;
        while(true)
        {
            int n=sock->Recv(&buffer_queue);
            if(n>0)
            {
                std::string json_package;
                bool ret=Decode(buffer_queue,&json_package);
                if(!ret)
                    continue;
                Request req;
                bool ok=req.Deserialiaze(json_package);
                if(!ok)
                    continue;
                Response resp =_func(req);
                std::string json_str=resp.Serialize();
                std::string send_str=Encode(json_str);
                sock->Send(send_str);
            }
            else if(n == 0)
            {
                LOG(log_level::INFO) << "client:" << client.addr_name() << "Quit!";
                break;
            }
            else 
            {
                LOG(log_level::WARNING) << "client:" << client.addr_name() << ", recv error";
                break;
            }
        }
    }
    ~Protocol()
    {
    }
private:
    func_t _func;
};